home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / inter52e.zip / INTSUM16.ZIP / LISTFILE.CPP < prev    next >
C/C++ Source or Header  |  1996-10-13  |  25KB  |  785 lines

  1. //********************************************************************
  2. //  LISTFILE.CPP - Handle ListFile display, searching, etc.           
  3. //                                                                    
  4. //  Copyright (c) 1996 Daniel D. Miller                               
  5. //                                                                    
  6. //  Last Update:  09-04-95 11:17pm                                    
  7. //                                                                    
  8. //  Compile with makefile                                             
  9. //                                                                    
  10. //********************************************************************
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <dos.h>
  16. #include "intsum.hpp"
  17. #include "err_exit.hpp"
  18. #include "keycodes.h"
  19. // #include <memcheck.h>
  20.  
  21. static char srchstr[81] ;
  22.  
  23. //*****************************************************************
  24. static void fill_list_buffers(fpos_t pos);
  25. static int  search_list_buffers(void);
  26. static void search_list_file(void);
  27. static void back_up_list1(void);
  28.  
  29. //*****************************************************************
  30. void process_list_file(int list_mode, char *save_file)
  31.    {
  32.    char sfile[128], sname[13] ;
  33.    char lstr[sizeof(sum_conv)+1] ;
  34.    unsigned j, ref_bfr ;
  35.  
  36.    int_sum_line *iptr = (int_sum_line *) lstr ;
  37.  
  38.    dprints(0, 2, LOGO, list_header) ;
  39.    dprints(0, 3, LOGO, list_dividerd) ;
  40.  
  41.    //  initialize list-file variables which are not
  42.    //  otherwise later set up.
  43.    list.offset = 0 ; 
  44.    list.cur_bfr = 0 ;
  45.    list.hdptr[0] = 0L ;
  46.  
  47.    //  figure out which line in ref file was selected
  48.    ref_bfr = (unsigned) ref.cur_bfr ;
  49.    unsigned currow = ref.offset + ivideo.currow - DATA_TOP ;
  50.    if (currow > (ref.lines[0] + ref.lines[1])) 
  51.       return ;
  52.    if (ref.cur_bfr == 0  &&  currow > ref.lines[0]) 
  53.       {
  54.       ref_bfr = 1 ;
  55.       currow -= ref.lines[0] ;
  56.       }
  57.    else if (ref.cur_bfr == 1  &&  currow > ref.lines[1]) 
  58.       return ;
  59.  
  60.    //  read appropriate data into list-file struct.
  61.    strcpy(lstr, ref.bfr[ref_bfr][currow].instr) ;
  62.  
  63.    if (iptr->file == ' ') 
  64.       {
  65.       _makepath(sfile, ildrive, ilpath, "interrup", "lst") ;
  66.       strcpy(sname,"interrup.lst") ;
  67.       }
  68.    else 
  69.       {
  70.       char c2s[5] ;
  71.       c2s[0] = iptr->file ;
  72.       c2s[1] = NULL ;
  73.       _makepath(sfile, ildrive, ilpath, "interrup", c2s) ;
  74.       _makepath(sname, NULL, NULL, "interrup", c2s) ;
  75.       }
  76.  
  77.    //  determine file offset
  78.    iptr->null_term = 0 ;
  79.    fpos_t loffset = strtol(iptr->foffset, NULL, 16) ;
  80.  
  81.    //  open the file
  82.    lfile = fopen(sfile, "rb") ;
  83.    if (lfile == NULL) 
  84.       error_exit(NO_READ_FILE, sfile) ;
  85.  
  86.    fill_list_buffers(loffset) ;  //  fill the list buffers
  87.  
  88.    //  now, determine whether this is a "print topic" call 
  89.    //  or a normal "display" call
  90.    if (list_mode == 1) 
  91.       {
  92.       //  open the output file
  93.       FILE* outfile = fopen(save_file, "wt") ;
  94.       if (outfile == NULL) 
  95.          {
  96.          strupr(save_file) ;
  97.          sprintf(tempstr, "cannot open %s", save_file) ;
  98.          message_show(tempstr) ;
  99.          fclose(lfile) ;
  100.          dprints(0, 2, LOGO, header) ;
  101.          dprints(0, 3, LOGO, dividerd) ;
  102.          return ;
  103.          }
  104.  
  105.       //  write the data into it
  106.       ref_bfr = 0 ;  //  overloading this variable
  107.       j=0 ;
  108.       do {
  109.          fprintf(outfile, "%s\n", list.bfr[ref_bfr][j].instr) ;
  110.          if (++j > list.lines[ref_bfr]) 
  111.             {
  112.             j = 0 ;
  113.             if (++ref_bfr == 2) 
  114.                {
  115.                fill_list_buffers(list.tlptr[1]) ;  //  refill the list buffers
  116.                ref_bfr = 0 ;
  117.                }
  118.             }
  119.          }
  120.       while (strncmp(list.bfr[ref_bfr][j].instr, "--------", 8) != 0) ;
  121.  
  122.       //  close files and exit
  123.       fclose(outfile) ;
  124.       fclose(lfile) ;
  125.       dprints(0, 2, LOGO, header) ;
  126.       dprints(0, 3, LOGO, dividerd) ;
  127.       return ;
  128.       }
  129.  
  130.    //  display current filename on screen
  131.    dprints(1, 2, FILENAME, sname) ;
  132.  
  133.    //  display the first buffer of data
  134.    ivideo.currow = DATA_TOP ;
  135.    display_list_file() ;
  136.  
  137.    //  list-file keyboard handler
  138.    srchstr[0] = 0 ;  //  reset the search string
  139.    unsigned rtemp ;
  140.    int count ;
  141.    int done = 0 ;
  142.    while (!done) 
  143.       {
  144.       mark_cursor_line(ivideo.currow, SELECTED) ;
  145.       unsigned indata = get_key() ;
  146.       mark_cursor_line(ivideo.currow, MAIN_TEXT) ;
  147.       switch (indata) 
  148.          {
  149.          case Key_UP:
  150.             scroll_list_down() ;
  151.             break;
  152.  
  153.          case Key_PGUP:
  154.             rtemp = ivideo.currow ;
  155.             ivideo.currow = DATA_TOP ;
  156.             for (j=0; j<window_rows; j++) 
  157.                scroll_list_down() ;
  158.             ivideo.currow = rtemp ;
  159.             break;
  160.  
  161.          case Key_DOWN:
  162.             scroll_list_up() ;
  163.             break;
  164.  
  165.          case Key_PGDN:
  166.             rtemp = ivideo.currow ;
  167.             ivideo.currow = screen_rows - 1 ;
  168.             for (j=0; j<window_rows; j++) 
  169.                scroll_list_up() ;
  170.             ivideo.currow = rtemp ;
  171.             break;
  172.  
  173.          case Key_HOME:
  174.             loffset = 0 ;
  175.             fill_list_buffers(loffset) ;
  176.             list.offset = 0 ;
  177.             list.cur_bfr = 0 ;
  178.             ivideo.currow = DATA_TOP ;
  179.             display_list_file() ;
  180.             break;
  181.  
  182.          case Key_END:
  183.             //  seek end of file
  184.             fseek(lfile, 0L, SEEK_END) ;
  185.             fgetpos(lfile, &loffset) ;
  186.             loffset -= REV_SIZE ;
  187.  
  188.             //  adjust input-file position, then
  189.             //  read one line and re-position file pointer to full line
  190.             fsetpos(lfile, &loffset) ;
  191.             count = seek_next_line(lfile) ;
  192.             if (count < 0) 
  193.                error_exit(BAD_SEARCH, NULL) ;
  194.             loffset += count ;
  195.             fill_list_buffers(loffset) ;
  196.  
  197.             //  now, figure out which line is top of (end of screen)
  198.             if (list.lines[1] < window_rows) 
  199.                {
  200.                list.cur_bfr = 0 ;
  201.                list.offset =  list.lines[0] + list.lines[1] - window_rows ;
  202.                }
  203.             else 
  204.                {
  205.                list.cur_bfr = 1 ;
  206.                list.offset = list.lines[1] - window_rows ;
  207.                }
  208.  
  209.             ivideo.currow = DATA_TOP ;
  210.             display_list_file() ;
  211.             break;
  212.  
  213.          case Key_F1:
  214.          case Key_h:
  215.          case Key_H: //  display help screen
  216.             display_help() ;
  217.             display_logo() ;
  218.             dprints(0, 2, LOGO, list_header) ;
  219.             display_list_file() ;
  220.             break;
  221.  
  222.          case Key_F2:
  223.          case Key_s:
  224.          case Key_S: //  search for string
  225.             if (message_read("Enter string to search for: ", srchstr) == 0)
  226.                {
  227.                if (search_list_buffers() != 0) 
  228.                    search_list_file() ;
  229.                }
  230.             //  redraw current filename on screen
  231.             dprints(0, 2, LOGO, list_header) ;
  232.             dprints(1, 2, FILENAME, sname) ;
  233.             break;
  234.  
  235.          case Key_F3:
  236.          case Key_r:
  237.          case Key_R: //  repeat last string search
  238.             if (strlen(srchstr) == 0) 
  239.                message_show("There is no current search string") ;
  240.             else if (search_list_buffers() != 0) 
  241.                 search_list_file() ;
  242.             //  redraw current filename on screen
  243.             dprints(0, 2, LOGO, list_header) ;
  244.             dprints(1, 2, FILENAME, sname) ;
  245.             break;
  246.  
  247.          case Key_ESC:
  248.             fclose(lfile) ;
  249.             dprints(0, 2, LOGO, header) ;
  250.             dprints(0, 3, LOGO, dividerd) ;
  251.             done = 1 ;
  252.             break;
  253.  
  254.          default:
  255.             break;
  256.          }  //  keyboard switch
  257.       }  //  while not done
  258.    }
  259.  
  260. //*****************************************************************
  261. void fill_list_buffers(fpos_t pos)
  262.    {
  263.    //  adjust input-file position
  264.    fsetpos(lfile, &pos) ;
  265.    list.hdptr[0] = pos ;
  266.  
  267.    // read data and fill list_list buffer 0
  268.    list.lines[0] = fill_list_bfr(0) ; //  fill forward buffer
  269.  
  270.    // read data and fill list_list buffer 1
  271.    list.hdptr[1] = list.tlptr[0] ;
  272.    list.lines[1] = fill_list_bfr(1) ; //  fill aft buffer
  273.    }
  274.  
  275. //*****************************************************************
  276. //  first, search current list buffer(s) starting at list.offset.
  277. //*****************************************************************
  278. int search_list_buffers(void)
  279.    {
  280.    unsigned sline = list.offset + (ivideo.currow - DATA_TOP) + 1 ;
  281.    int srch_done ;
  282.    //  first, search list.bfr0 if active
  283.    if (list.cur_bfr == 0) 
  284.       {
  285.       srch_done = 0 ;
  286.       if (sline <= list.lines[0]) 
  287.          {
  288.          while (!srch_done) 
  289.             {
  290.             //  If string is found, update buffers and move cursor
  291.             if (strstri(list.bfr[0][sline].instr, srchstr) == 0) 
  292.                {
  293.                list.offset = sline ;
  294.                //  I _think_ this is the correct position
  295.                search.offset = sline ;
  296.                list.offset = sline ;
  297.  
  298.                ivideo.currow = DATA_TOP ;
  299.                display_list_file() ;
  300.                return 0;
  301.                }
  302.             //  string is not yet found; move along in buffer0
  303.             //  if at end of buffer, exit and try buffer 1.
  304.             else if (++sline >= list.lines[0]) 
  305.                {
  306.                srch_done = 1 ;
  307.                sline = 0 ;
  308.                }
  309.             }  //  while not done searching
  310.          }  //  if first search line actually IS in bfr0
  311.       //  if search line lapses into bfr1, move there
  312.       else 
  313.          {
  314.          sline -= list.lines[0] ;
  315.          }
  316.       }
  317.  
  318.    //  then, search list.bfr1 if active, and nothing found in 0
  319.    if (list.lines[1] > 0) 
  320.       {
  321.       srch_done = 0 ;
  322.       while (!srch_done) 
  323.          {
  324.          //  If string is found, update buffers and move cursor
  325.          if (strstri(list.bfr[1][sline].instr, srchstr) == 0) 
  326.             {
  327.             search.offset = sline ;
  328.             list.cur_bfr = 1 ;
  329.             list.offset = sline ;
  330.             ivideo.currow = DATA_TOP ;
  331.             display_list_file() ;
  332.             return 0;
  333.             }
  334.          //  string is not yet found; move along in buffer1.
  335.          //  if at end of buffer, exit and try other buffers.
  336.          else if (++sline >= list.lines[1]) 
  337.             {
  338.             srch_done = 1 ;
  339.             sline = 0 ;
  340.             }
  341.          }  //  while not done searching
  342.       }  //  if any lines are in buffer1, search it
  343.  
  344.    return -1 ;
  345.    }
  346.  
  347. //*****************************************************************
  348. //  current buffers have already been searched, with nothing found.
  349. //  Now, search list file starting at list.tlptr[1].
  350. //*****************************************************************
  351. void search_list_file(void)
  352.    {
  353.    //  first, save current file pointer so it
  354.    //  can be restored if no match is found.
  355.    fpos_t oldpos ;
  356.    fgetpos(lfile, &oldpos) ;
  357.  
  358.    //  position file pointer to current cursor position
  359.    search.hdptr = list.tlptr[1] ;
  360.    fsetpos(lfile, &search.hdptr) ;
  361.    //  move past it to current line (if possible)
  362.  
  363.    //  fill the readbfr from list file
  364.    unsigned rlines = fill_search_buffer(lfile) ;
  365.    if (rlines == 0) 
  366.       {
  367.       message_show("Your search string was not found") ;
  368.       return ;
  369.       }
  370.  
  371.    unsigned sline = 0 ;
  372.    int srch_done = 0 ;
  373.    while (!srch_done) 
  374.       {
  375.       //  If string is found, update buffers and move cursor
  376.       if (strstri(search.bfr[sline].instr, srchstr) == 0) 
  377.          {
  378.          // read real data from beginning of current block
  379.          fill_list_buffers(search.hdptr) ;
  380.  
  381.          //  I _think_ this is the correct position
  382.          search.offset = sline ;
  383.          list.offset = sline ;
  384.          list.cur_bfr = 0 ;
  385.  
  386.          ivideo.currow = DATA_TOP ;
  387.          display_list_file() ;
  388.          srch_done = 1 ;
  389.          }
  390.       //  string is not yet found; move along in readbfr.
  391.       //  if at end of buffer, read next buffer or fail.
  392.       else if (++sline >= rlines) 
  393.          {
  394.          search.hdptr = search.tlptr ;
  395.          rlines = fill_search_buffer(lfile) ;
  396.          if (rlines == 0) 
  397.             {
  398.             //  restore input-file position
  399.             fsetpos(lfile, &oldpos) ;
  400.             srch_done = -1 ;
  401.             message_show("Your search string was not found") ;
  402.             }
  403.          else 
  404.             {
  405.             sline = 0 ;
  406.             }
  407.          }
  408.       }  //  while not done searching
  409.    }
  410.  
  411. //*****************************************************************
  412. void scroll_list_down(void)
  413.    {
  414.    //  if cursor is NOT at top, move cursor
  415.    if (ivideo.currow > DATA_TOP) 
  416.       {
  417.       ivideo.currow-- ;
  418.       }
  419.    //  if cursor IS at top, try to move up in current buffer
  420.    else if (list.offset > 0)  //  scroll window down
  421.       {
  422.       list.offset-- ;
  423.       display_list_file() ;
  424.       }
  425.    //  if current buffer is 1, just move back to buffer 0
  426.    else if (list.cur_bfr == 1)
  427.       {
  428.       list.cur_bfr = 0 ;
  429.       list.offset = list.lines[0] - 1 ;
  430.       display_list_file() ;
  431.       }
  432.    //  if current buffer = 0, see if we're at beginning of file.
  433.    //  if so, do nothing; otherwise, try to read back in buffer,
  434.    //  after copying buffer 0 to buffer 1.
  435.    else if (list.hdptr[0] > 0) 
  436.       {
  437.       //  copy buffer0 values to buffer1
  438.  
  439.       //  swap the buffer pointers
  440.       lines *b    = list.bfr[0] ;
  441.       list.bfr[0] = list.bfr[1] ;
  442.       list.bfr[1] = b ;
  443.  
  444.       list.lines[1] = list.lines[0] ;
  445.       list.hdptr[1] = list.hdptr[0] ;
  446.       list.tlptr[1] = list.tlptr[0] ;
  447.       //  current buffer remains 0.
  448.       // list.cur_bfr = 0 ;
  449.  
  450.       //  then compute and read new data into buffer0
  451.       fill_list_bfr_rev() ; //  fill forward buffer
  452.       if (list.offset > 0) 
  453.          list.offset-- ;
  454.       display_list_file() ;
  455.       }
  456.    }
  457.  
  458. //*****************************************************************
  459. void scroll_list_up(void)
  460.    {
  461.    // end_line is line number for NEXT line
  462.    unsigned end_line = list.offset + window_rows ; //  base-0
  463.  
  464.    //  if still onscreen, just move cursor
  465.    if (ivideo.currow+1 < screen_rows) 
  466.       {
  467.       ivideo.currow++ ;
  468.       }
  469.  
  470.    //  end of screen...
  471.    //  see if there's still room in buffer to move cursor
  472.    else if (end_line < list.lines[list.cur_bfr])
  473.          //   ^base-0        ^base-1     
  474.       {
  475.       list.offset++ ;
  476.       display_list_file() ;
  477.       }
  478.  
  479.    //  we are at end of buffer
  480.  
  481.    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  482.    //                      BUFFER 0                             
  483.    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  484.    else if (list.cur_bfr == 0) 
  485.    //  If we're in buffer0, we should be able to slop over
  486.    //  into buffer1, if there's any data in it.
  487.       {
  488.       //  if we were previously in buffer0, but now (after     
  489.       //  adding one line) we don't fit in buffer0+buffer1,    
  490.       //  there were less than (screen_size) lines in buffer1, 
  491.       //  which means we're at end of file (otherwise, we      
  492.       //  would have read roughly 32Kbytes).                   
  493.       //                                                       
  494.       //  NOTE: we do not currently handle scrolling           
  495.       //        across multiple files.                         
  496.       //                                                       
  497.       if (end_line >= (list.lines[0] + list.lines[1])) 
  498.          {
  499.          //  do nothing for now...
  500.          //  Later, we'll add multiple-file support.
  501.          }
  502.       //  If there is room in the two combined files, see if
  503.       //  moving to next line has thrown us COMPLETELY into buffer1.
  504.       else if ((list.offset+1) == list.lines[0])
  505.          {
  506.          list.offset = 0 ;
  507.          list.cur_bfr = 1 ;
  508.          display_list_file() ;
  509.          }
  510.       //  otherwise, we're overlapping two files, 
  511.       //  which the list function supports internally.
  512.       else
  513.          {
  514.          list.offset++ ;
  515.          display_list_file() ;
  516.          }
  517.       }
  518.  
  519.    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  520.    //                      BUFFER 1                             
  521.    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  522.    //  if NOT at end of buffer 1, update array offset and redraw
  523.    else if (end_line < list.lines[1]) 
  524.          //  ^base0      ^base1     
  525.       {
  526.       list.offset++ ;
  527.       display_list_file() ;
  528.       }
  529.    //  if we reach end of buffer 1, 
  530.    //  copy buffer 1 to buffer 0 and see if
  531.    //  there's more data to scroll into.
  532.    else 
  533.       {
  534.       back_up_list1() ;
  535.       if (list.lines[1] > 0) 
  536.          {
  537.          list.offset++ ;
  538.          display_list_file() ;
  539.          }
  540.       }
  541.    }
  542.  
  543. //*****************************************************************
  544. void back_up_list1(void)
  545.    {
  546.    //  swap the buffer pointers
  547.    lines *b      = list.bfr[0] ;
  548.    list.bfr[0]   = list.bfr[1] ;
  549.    list.bfr[1]   = b ;
  550.    //  copy buffer1 data to buffer0 struct
  551.    list.lines[0] = list.lines[1] ;
  552.    list.hdptr[0] = list.hdptr[1] ;
  553.    list.tlptr[0] = list.tlptr[1] ;
  554.    list.cur_bfr  = 0 ;
  555.    list.hdptr[1] = list.tlptr[0] ;
  556.  
  557.    //  read new data into buffer1
  558.    list.lines[1] = fill_list_bfr(1) ;
  559.    }
  560.  
  561. //*****************************************************************
  562. void display_list_file(void)
  563.    {
  564.    //  buffer_left is 1-based
  565.    unsigned j, buffer_left = list.lines[list.cur_bfr] - list.offset ;
  566.            //     ^base-1            ^base-1             ^base-0
  567.  
  568.    //  if current buffer fits entirely onscreen
  569.    if (window_rows <= buffer_left) 
  570.       {
  571.       for (j=0; j<window_rows; j++) 
  572.          {
  573.          dprints(0, DATA_TOP+j, MAIN_TEXT, 
  574.             list.bfr[list.cur_bfr][list.offset+j].instr) ;
  575.          }
  576.       }
  577.    //  if we're currently using buffer 0, just lop over into bfr 1
  578.    //  Fill any unused lines with blank lines.
  579.    else if (list.cur_bfr == 0)
  580.       {
  581.       if (window_rows > (buffer_left + list.lines[1])) 
  582.          //  ^base1        ^base1         ^base1
  583.          {
  584.          //  draw remainder of buffer0
  585.          for (j=0; j<buffer_left; j++) 
  586.             {
  587.             dprints(0, DATA_TOP+j, MAIN_TEXT, 
  588.                list.bfr[0][list.offset+j].instr) ;
  589.             }
  590.          //  draw all of buffer1
  591.          unsigned new_top = DATA_TOP + buffer_left ;
  592.          for (j=0; j<list.lines[1]; j++) 
  593.             {
  594.             dprints(0, new_top++, MAIN_TEXT, list.bfr[1][j].instr) ;
  595.             }
  596.          //  draw blank lines
  597.          spaces[80] = 0 ;
  598.          //for (j=new_top; j<screen_rows; j++) 
  599.          while (new_top < screen_rows) 
  600.             {
  601.             dprints(0, new_top++, MAIN_TEXT, spaces) ;
  602.             }
  603.          spaces[80] = ' ' ;
  604.          }
  605.       else 
  606.          {
  607.          for (j=0; j<buffer_left; j++) 
  608.             {
  609.             dprints(0, DATA_TOP+j, MAIN_TEXT, 
  610.                list.bfr[0][list.offset+j].instr) ;
  611.             }
  612.          for (j=0; j<(window_rows-buffer_left); j++) 
  613.             {
  614.             dprints(0, DATA_TOP+buffer_left+j, MAIN_TEXT, 
  615.                     list.bfr[1][j].instr) ;
  616.             }
  617.          }
  618.       }
  619.    //  we're at end of buffer 1; are we at EOF??
  620.    else 
  621.       {
  622.       //  copy buffer1 to buffer0,
  623.       //  then refill buffer 1.
  624.       back_up_list1() ;
  625.  
  626.       //  recursively call this display routine
  627.       display_list_file() ;
  628.       }
  629.    }
  630.  
  631. //*****************************************************************
  632. //  parse lines from input file.
  633. //*****************************************************************
  634. const unsigned TAB_SIZE = 8 ;
  635.  
  636. unsigned fill_list_bfr(unsigned bfr_flag)
  637.    {
  638.    int done = 0 ;
  639.    //lint -e740
  640.    unsigned offseti = FP_OFF(readptr) ;   // init value for byte tfr counter
  641.    unsigned offsetf ;
  642.    unsigned count = 0, j ;
  643.  
  644.    //  fill the readbfr from list file
  645.    unsigned rlines = fill_read_buffer(lfile) ;
  646.    if (rlines == 0) 
  647.       return 0;
  648.  
  649.    //  now, translate the read buffer into the list-list buffer
  650.    unsigned lcount = 0 ;   // output_buffer counter
  651.    char *sptr = readptr ;
  652.    while (!done) 
  653.       {
  654.       unsigned slen = strlen(sptr) ;
  655.  
  656.       if (slen == 0) //  insert a blank line
  657.          {
  658.          spaces[80] = 0 ;
  659.          strcpy(list.bfr[bfr_flag][lcount].instr, spaces) ;
  660.          spaces[80] = ' ' ;
  661.          }
  662.  
  663.       //  copy data to list buffer.  strcpy() won't do because
  664.       //  TABs have to be converted from the input files.
  665.       //strcpy(list.bfr[bfr_flag][lcount].instr, sptr) ;
  666.       else 
  667.          {
  668.          char* cptr = sptr ;
  669.          j = 0 ;
  670.          while (j < 80  &&  *cptr != 0) 
  671.             {
  672.             switch (*cptr) 
  673.                {
  674.                case TAB:
  675.                   do {
  676.                      if (j < 80) 
  677.                         {
  678.                         list.bfr[bfr_flag][lcount].instr[j] = ' ' ;
  679.                         }
  680.                      j++ ;
  681.                      }
  682.                   while ((j % TAB_SIZE) != 0);
  683.                   cptr++ ; //  strip the TAB char from input
  684.                   break;
  685.  
  686.                default:
  687.                   list.bfr[bfr_flag][lcount].instr[j++] = *cptr++ ;
  688.                   break;
  689.                }  //  switch (input char)
  690.             }
  691.  
  692.          //  if input line is longer than 80 chars, skim ahead to EOL
  693.          if (j == 80) 
  694.             {
  695.             while (*cptr != 0)  cptr++ ;
  696.             }
  697.          else
  698.             {
  699.             //  pad short lines with spaces
  700.             while (j < 80) 
  701.                {
  702.                list.bfr[bfr_flag][lcount].instr[j++] = ' ' ;
  703.                }
  704.             }
  705.          list.bfr[bfr_flag][lcount].instr[80] = 0 ;  //  NULL-term the line
  706.  
  707.          //  point to next string in buffer
  708.          sptr += slen ;
  709.          }  //  copy line to list buffer, expanding TABs
  710.  
  711.       //  skip NULLs, which were formerly CR/LF
  712.       //  Skipping ALL NULLs is not appropriate, as this
  713.       //  effectively deletes blank lines.
  714.       //  We should skip at most 2 NULLs, then add all
  715.       //  further NULL pairs as blank lines.
  716.       if (*sptr == NULL) sptr++ ;   //  skip CR
  717.       if (*sptr == NULL) sptr++ ;   //  skip LF
  718.       count++ ;
  719.       lcount++ ;
  720.  
  721.       //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  722.       //  Determine if we are at end of input data (count),
  723.       //  or if output buffer is full (lcount)
  724.       //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  725.       if (lcount == list_lines  ||  count == rlines) 
  726.          {
  727.          done = 1 ;
  728.          //  set tail-pointer variable in current list struct
  729.          offsetf = FP_OFF(sptr) ;   //lint !e740
  730.          list.tlptr[bfr_flag] = list.hdptr[bfr_flag] + (offsetf - offseti) ;
  731.          //  adjust input-file position
  732.          fpos_t pos = list.tlptr[bfr_flag] ;
  733.          fsetpos(lfile, &pos) ;
  734.          }
  735.       }  //  while not done filling input buffer
  736.  
  737.    return count;
  738.    }
  739.  
  740. //*****************************************************************
  741. void fill_list_bfr_rev(void)
  742.    {
  743.    unsigned count ;
  744.    int done, icount ;
  745.  
  746.    //  make a copy of current line before overwriting it,
  747.    //  so we can find it again afterwards
  748.    strcpy(oldstr, list.bfr[1][list.offset].instr) ;
  749.    if (strlen(oldstr) == 0) 
  750.       error_exit(BAD_FORMAT, NULL) ;
  751.  
  752.    //  figure out how far to back up the read pointer
  753.    fpos_t pos = IFF   (list.hdptr[0] > REV_SIZE) 
  754.                 THENN (list.hdptr[0] - REV_SIZE)
  755.                 ELSSE 0 ;
  756.  
  757.    //  now read one line and re-position file pointer to full line
  758.    //  (if we're at beginning of file, don't bother)
  759.    if (pos > 0) 
  760.       {
  761.       fsetpos(lfile, &pos) ;
  762.       icount = seek_next_line(lfile) ;
  763.       if (icount < 0) 
  764.          error_exit(BAD_SEARCH, NULL) ;
  765.       pos += icount ;
  766.       }
  767.    fill_list_buffers(pos) ;
  768.  
  769.    //  now that new buffers have been read, 
  770.    //  seek to the current line and update list.offset
  771.    count = 0 ;
  772.    done = 0 ;
  773.    while (!done) 
  774.       {
  775.       if (strcmp(oldstr, list.bfr[0][count].instr) == 0) 
  776.          {
  777.          list.offset = count ;
  778.          done = 1 ;
  779.          }
  780.       else if (++count >= list.lines[0])
  781.          error_exit(BAD_SEARCH, NULL) ; 
  782.       }
  783.    }
  784.  
  785.